/**
 *  @file SSLSocketFactory.h
 */
#ifndef _SSLSOCKETFACTORY_H_
#define _SSLSOCKETFACTORY_H_

#include "../SocketFactory.h"
#include "SSLCallbacks.h"
#include "../../collections/ListT.h"

namespace cppflib
{

class CFString;

namespace net
{

class Socket;

namespace ssl 
{ 

class SSLContext;

/**
 *  Socket factory for SSL client
 */
class _DLLAPI SSLSocketFactory : public SocketFactory
{
public:
    typedef enum
    {
       NOTVERIFY,       ///< not check peer's host name in the cert
       VERIFYHOSTNAME   ///< verify peer's host name
    } verifyhostname_t;

private:
    SSLContext *pSSLCtxt;
    ISSLPeerCertCallback *pPeerCertCb;
    verifyhostname_t verifyType;

private:
    void ReleaseBeforeThrowing();

public:
    SSLSocketFactory(void);

    SSLSocketFactory(const CFString &rootCertPath, ISSLPeerCertCallback *pPeerCertCb);

    SSLSocketFactory(const CFString &rootCertPath, ISSLPeerCertCallback *pPeerCertCb,
                     const CFString &clientCertPath, ISSLPrivateKeyPwdCallback *pPrivateKeyPwdCb);
    
    virtual ~SSLSocketFactory(void);

    virtual Socket * CreateSocket(bool isSSL, const CFString &socketAddress, u16_t socketPort);
    virtual bool CreateListeningSockets(collections::ListCppObjT<Socket> &sockList, int backLog);

    void SetVerifyHostnameType(verifyhostname_t type);
    verifyhostname_t GetVerifyHostnameType();
};


/**
 *  Derived from VirtualHostInfo. SSLVirtualHostInfo contains more info than a VirtualHostInfo.
 *
 *  One "hostAddr, port" pair corresponds to one server certificate
 */
class _DLLAPI SSLVirtualHostInfo : public VirtualHostInfo
{  
private:
   SSLVirtualHostInfo();
   virtual bool AddVirtualHost(const CFString & hostAddr);

public:
   virtual ~SSLVirtualHostInfo();

   SSLVirtualHostInfo(u16_t listenPort, const CFString & bindAddr, const CFString & hostAddr, 
                  const CFString & serverCertPath,
                  ISSLPrivateKeyPwdCallback *pPrivateKeyPwdCb, ISSLPeerCertCallback *pPeerCertCb,
                  bool needClientAuth);
   
   bool AddVirtualHost(const CFString & hostAddr, const CFString & serverCertPath,
                       ISSLPrivateKeyPwdCallback *pPrivateKeyPwdCb, ISSLPeerCertCallback *pPeerCertCb,
                       bool needClientAuth);
   
   friend class SSLServerSocketFactory;
};

/**
 *  Socket factory for SSL server
 */
class _DLLAPI SSLServerSocketFactory : public SocketFactory
{
private:
    SSLServerSocketFactory(void);

public:
    SSLServerSocketFactory(const CFString &rootCertPath, collections::ListCppObjT<VirtualHostInfo> * pVHInfoList);
    virtual ~SSLServerSocketFactory(void);

    virtual Socket * CreateSocket(bool isSSL, const CFString &serverAddress, u16_t listenPort);
    virtual bool CreateListeningSockets(collections::ListCppObjT<Socket> &sockList, int backLog);
};

} // end of namespace ssl

} // end of namespace net

} // end of namespace cppflib


#endif
